package com.yyaccp.hncc.oss.aliyun.service;

import com.aliyun.oss.OSS;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.MatchMode;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.oss.model.PolicyConditions;
import com.yyaccp.hncc.common.vo.oss.OssCallbackResult;
import com.yyaccp.hncc.common.vo.oss.OssPolicyResult;
import com.yyaccp.hncc.common.vo.oss.UploadResult;
import com.yyaccp.hncc.oss.aliyun.config.OssConfig;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.utils.DateUtils;
import org.codehaus.jettison.json.JSONObject;
import org.springframework.stereotype.Service;
import org.springframework.util.FileCopyUtils;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Date;
import java.util.Map;
import java.util.UUID;

/**
 *
 * @author 天天向上 （john.yi@qq.com）
 * @date 2020/8/18
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class OssServiceImpl implements OssService {
    private final OSS ossClient;
    private final OssConfig ossConfig;

    @Override
    public OssPolicyResult ossPolicy() {
        OssPolicyResult ossPolicyResult = new OssPolicyResult();
        // host的格式为 bucketname.endpoint
        String host = "http://" + ossConfig.getBucketName() + "." + ossConfig.getEndpoint();
        // callbackUrl为 上传回调服务器的URL，请将下面的IP和Port配置为您自己的真实信息。
        String callbackUrl = ossConfig.getCallback();
        try {
            long expireEndTime = System.currentTimeMillis() + ossConfig.getExpire() * 1000;
            Date expiration = new Date(expireEndTime);
            PolicyConditions policyConds = new PolicyConditions();
            policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, ossConfig.getMaxSize() * 1024 * 1024);
            policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, ossConfig.getDirPrefix());

            String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);
            byte[] binaryData = postPolicy.getBytes("utf-8");
            String encodedPolicy = BinaryUtil.toBase64String(binaryData);
            String postSignature = ossClient.calculatePostSignature(postPolicy);
            // 封装签名结果
            ossPolicyResult.setAccessKeyId(ossConfig.getAccessKeyId());
            ossPolicyResult.setPolicy(encodedPolicy);
            ossPolicyResult.setSignature(postSignature);
            ossPolicyResult.setDir(ossConfig.getDirPrefix());
            ossPolicyResult.setHost(host);
            ossPolicyResult.setExpire(String.valueOf(expireEndTime / 1000));
            // 设置回调参数
            JSONObject jasonCallback = new JSONObject();
            jasonCallback.put("callbackUrl", callbackUrl);
            jasonCallback.put("callbackBody",
                    "filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}");
            jasonCallback.put("callbackBodyType", "application/x-www-form-urlencoded");
            String base64CallbackBody = BinaryUtil.toBase64String(jasonCallback.toString().getBytes());
            // 设置回调内容
            ossPolicyResult.setCallbackBody(base64CallbackBody);
        } catch (Exception e) {
            log.error("创建oss签名失败", e);
        }
        return ossPolicyResult;
    }

    @Override
    public OssCallbackResult ossCallback(Map<String, String[]> paramterMap) {
        OssCallbackResult ossCallbackResult = new OssCallbackResult();
        String filename = paramterMap.get("filename")[0];
        filename = "https://".concat(ossConfig.getBucketName()).concat(".").concat(ossConfig.getEndpoint()).concat("/").concat(filename);
        ossCallbackResult.setFilename(filename);
        ossCallbackResult.setHeight(paramterMap.get("height")[0]);
        ossCallbackResult.setMimeType(paramterMap.get("mimeType")[0]);
        ossCallbackResult.setSize(paramterMap.get("size")[0]);
        ossCallbackResult.setWidth(paramterMap.get("width")[0]);
        return ossCallbackResult;
    }

    @Override
    public UploadResult upload(String originalFilename, InputStream in) {
        String filename = UUID.randomUUID().toString() + originalFilename.substring(originalFilename.lastIndexOf("."));
        String yyyyMMdd = DateUtils.formatDate(new Date(), "yyyyMMdd");
        String fullFilename = ossConfig.getDirPrefix() + yyyyMMdd + "/" + filename;
        ossClient.putObject(ossConfig.getBucketName(), fullFilename, in);
        UploadResult uploadResult = new UploadResult();
        uploadResult.setFilename(filename);
        uploadResult.setOriginalFilename(originalFilename);
        //需要到oss配置文件权限和跨域才能直接访问下面的url，否则会报403
        uploadResult.setUrl("http://" + ossConfig.getBucketName() + "." + ossConfig.getEndpoint() + "/" + fullFilename);
        return uploadResult;
    }

    @Override
    public String download(String filename, OutputStream outputStream) {
        OSSObject ossObject = ossClient.getObject(ossConfig.getBucketName(), ossConfig.getDirPrefix() + filename);
        String result = "error";
        try (InputStream inputStream = ossObject.getObjectContent()){
            FileCopyUtils.copy(inputStream, outputStream);
            result = "success";
        } catch (IOException e) {
            log.error("下载文件失败{}", filename, e);
        }
        return result;
    }
}
